package znet

import (
	"fmt"
	"net"
	"zinx/utils"
	"zinx/ziface"
)

type Server struct {
	Name      string
	IPVersion string
	IP        string
	Port      int
	//当前server的消息管理模块，负责绑定msgId和对应业务API的关系
	MsgHandler ziface.IMsgHandle
	//当前Server的连接管理器
	ConnMgr ziface.IConnManager
	//当前Server创建连接之后自动调用的Hook函数--OnConnCreate
	OnConnCreate func(conn ziface.IConnection)
	//当前Server销毁连接之前自动调用的Hook函数--OnConnDestroy
	OnConnDestroy func(conn ziface.IConnection)
}

func (s *Server) Start() {
	fmt.Printf("[Zinx] Server Name: %s, listening at IP: %s, Port: %d is starting\n", utils.GlobalObject.Name, utils.GlobalObject.Host, utils.GlobalObject.TcpPort)
	fmt.Printf("[Zinx] Version: %s, MaxConn: %d, MaxPackageSize: %d\n", utils.GlobalObject.Version, utils.GlobalObject.MaxConn, utils.GlobalObject.MaxPackageSize)
	fmt.Printf("[Start] Server Listener at IP: %s, Port %d, is starting\n", s.IP, s.Port)
	go func() {
		//0.开启工作队列池
		s.MsgHandler.StartWorkerPool()
		//1.获取一个TCP的Addr
		addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.Port))
		if err != nil {
			fmt.Println("resolve tcp addr error: ", err)
			return
		}
		//2.监听服务器对应地址
		listener, err := net.ListenTCP(s.IPVersion, addr)
		if err != nil {
			fmt.Println("listen ", s.IPVersion, " err: ", err)
			return
		}
		fmt.Println("start Zinx server succ, ", s.Name, " succ, Listening...")
		var cid uint32
		cid = 0
		//3.阻塞等待客户端连接，随后处理客户端的读写业务
		for {
			conn, err := listener.AcceptTCP()
			if err != nil {
				fmt.Println("accept err: ", err)
				continue
			}
			//设置最大连接数的判断
			if s.ConnMgr.Len() >= utils.GlobalObject.MaxConn {
				//TODO 给客户端响应一个超出最大连接的错误包
				fmt.Println("==================>Too Many Connections MaxConn = ", utils.GlobalObject.MaxConn)
				conn.Close()
				continue
			}
			//将处理新连接的业务方法和conn进行绑定，得到连接模块
			dealConn := NewConnection(s, conn, cid, s.MsgHandler)
			cid++
			//启动当前的连接模块业务处理功能
			go dealConn.Start()
		}
	}()
	select {}
}

func (s *Server) AddRouter(msgId uint32, router ziface.IRouter) {
	s.MsgHandler.AddRouter(msgId, router)
	fmt.Println("Add Router Success!")
}

func (s *Server) Stop() {
	//TODO 将一些服务器的资源、状态或者一些已经开辟的连接信息进行停止或者回收
	fmt.Println("[STOP] Zinx server name = ", s.Name)
	s.ConnMgr.ClearConn()
}

func (s *Server) Serve() {
	//启动Server的服务功能(异步)
	s.Start()

	//TODO 做一些启动服务器之后的额外业务

	//阻塞
	select {}
}

func (s *Server) GetConnMgr() ziface.IConnManager {
	return s.ConnMgr
}

func (s *Server) SetOnConnCreate(hookFunc func(connection ziface.IConnection)) {
	s.OnConnCreate = hookFunc
}

func (s *Server) SetOnConnDestroy(hookFunc func(connection ziface.IConnection)) {
	s.OnConnDestroy = hookFunc
}

func (s *Server) CallOnConnCreate(connection ziface.IConnection) {
	if s.OnConnCreate != nil {
		fmt.Println("------>Call OnConnCreate()...")
		s.OnConnCreate(connection)
	}
}

func (s *Server) CallOnConnDestroy(connection ziface.IConnection) {
	if s.OnConnDestroy != nil {
		fmt.Println("------>Call OnConnDestroy()...")
		s.OnConnDestroy(connection)
	}
}

func NewServer(name string) ziface.IServer {
	s := &Server{
		Name:       utils.GlobalObject.Name,
		IPVersion:  "tcp4",
		IP:         utils.GlobalObject.Host,
		Port:       utils.GlobalObject.TcpPort,
		MsgHandler: NewMsgHandle(),
		ConnMgr:    NewConnManager(),
	}
	return s
}
